<?php

/**
 * Here is your custom functions.
 */

define("mysqlType", [
    "int", "bigint", "decimal", "enum", "set", "json", "double", "tinytext", "varchar", "longtext", "text"
]); //数据库类型

/**
 * 获取当前的response 输出类型
 *
 * @return string
 */
function getResponseType(): string
{
    return request()->acceptJson() || request()->isAjax() ? 'json' : 'html';
}

/**
 * 操作成功跳转的快捷方法
 * @access protected
 * @param  mixed $msg 提示信息
 * @param  string $url 跳转的URL地址
 * @param  mixed $data 返回的数据
 * @param  integer $wait 跳转等待时间
 * @param  array $header 发送的Header信息
 * @return void
 */
function success($msg = '', string $url = null, $data = '', int $wait = 2, array $header = [])
{
    if (is_null($url) && isset($_SERVER["HTTP_REFERER"])) {
        $url = $_SERVER["HTTP_REFERER"];
    } elseif ($url) {
        $url = (strpos($url, '://') || 0 === strpos($url, '/')) ? $url : route($url);
    }

    $result = [
        'code' => 1,
        'msg' => $msg,
        'data' => $data,
        'url' => $url,
        'wait' => $wait,
    ];

    $type = getResponseType();
    if ('html' == strtolower($type)) {
        static $handler;
        if (null === $handler) {
            $handler = config('view.handler');
        }
        //模板路径 BASE_PATH . '/public/dispatch_jump.html'
        return response($handler::render(BASE_PATH . '/public/dispatch_jump.html', $result), 200, $header);
    } else {
        return json($result);
    }
}

/**
 * 操作错误跳转的快捷方法
 * @access protected
 * @param  mixed $msg 提示信息
 * @param  string $url 跳转的URL地址
 * @param  mixed $data 返回的数据
 * @param  integer $wait 跳转等待时间
 * @param  array $header 发送的Header信息
 * @return void
 */
function error($msg = '', string $url = null, $data = '', int $wait = 3, array $header = [])
{
    if (is_null($url)) {
        $url = request()->isAjax() ? '' : 'javascript:history.back(-1);';
    } elseif ($url) {
        $url = (strpos($url, '://') || 0 === strpos($url, '/')) ? $url : route($url);
    }

    $result = [
        'code' => 2,
        'msg' => $msg,
        'data' => $data,
        'url' => $url,
        'wait' => $wait,
    ];

    $type = getResponseType();

    if ('html' == strtolower($type)) {
        static $handler;
        if (null === $handler) {
            $handler = config('view.handler');
        }
        //模板路径 BASE_PATH . '/public/dispatch_jump.html'
        return response($handler::render(BASE_PATH . '/public/dispatch_jump.html', $result), 200, $header);
    } else {
        return json($result);
    }
}

/**
 * 验证器 function
 *
 * @param string $validate 验证类名
 * @param string $scene 场景名
 * @param array $data 验证数据
 * @return boolean
 */
function validate(string $validate, string $scene, array $data): bool
{
    $app = request()->app; //当前应用
    $class = 'app\\' . $app . '\\validate' . '\\' . $validate . "Validate";
    if (class_exists($class)) {
        $val = new $class;
        return $val->scene($scene)->failException(true)->check($data);
    } else {
        throw new \ErrorException("未定义验证类:$class");
    }
}

/**
 * 查看文件夹文件 function
 *
 * @param string $dir
 * @return array
 */
function selectDir(string $dir): array
{
    // 打开文件夹
    $files = [];
    if (is_dir($dir)) {
        if ($dh = opendir($dir)) {
            while (($filename = readdir($dh)) !== false) {
                // 忽略当前目录和父目录
                if ($filename != "." && $filename != "..") {
                    $files[] = $filename;
                }
            }
            closedir($dh);
        }
    }
    return $files;
}

use support\Log;

/**
 * 获取app注解 function
 *
 * @param string $app 应用名
 * @param boolean $is_page 是否页面
 * @param string $child_name 子名称
 * @return array
 */
function appAttribute(string $app, bool $is_page = true, string $child_name = "child"): array
{
    $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator(app_path()));
    $suffix = config('app.controller_suffix', '');
    $suffix_length = strlen((string)$suffix);
    $arr = [];
    $i = 0;
    foreach ($iterator as $file) {
        if (is_dir($file) || $file->getExtension() != 'php') {
            continue;
        }
        $file_path = str_replace('\\', '/', $file->getPathname());
        if (!str_contains(strtolower($file_path), '/controller/')) {
            continue;
        }
        if ($suffix_length && substr($file->getBaseName('.php'), -$suffix_length) !== $suffix) {
            continue;
        }
        $class_name = str_replace('/', '\\', substr(substr($file_path, strlen(base_path())), 0, -4));
        if (!class_exists((string)$class_name)) {
            echo "Class $class_name not found, skip route for it\n";
            continue;
        }
        $controller = new \ReflectionClass($class_name);
        $controllerClass = $controller->getAttributes(app\common\Attribute::class);
        $title = $controllerClass[0]->newInstance()->title();
        $ClassShortName = str_replace(config('app.controller_suffix', ''), "", $controller->getShortName());
        $arr[$i] = ["name" => $ClassShortName, "title" => $title, "spread" => true, "key" => $ClassShortName];
        foreach ($controller->getMethods(\ReflectionMethod::IS_PUBLIC) as $v) {
            if (in_array($v->name, ['__construct', '__destruct'])) {
                continue;
            }
            preg_match('/app(.*?)controller/', $v->class, $matches);
            if (str_replace('\\', "", $matches[1]) == $app) {
                if (empty($attributes = (new \ReflectionMethod($v->class, $v->name))->getAttributes(app\common\Attribute::class))) {
                    continue;
                }
                foreach ($attributes as $attribute) {
                    if ($data = array_merge([
                        "name" => ($MethodShortName = $v->name),
                        "spread" => true, "key" => "$ClassShortName@$MethodShortName"
                    ], $attribute->newInstance()->fun())) {
                        $arr[$i][$child_name][] =  $data;
                    }
                }
            }
        }
        ++$i;
    }
    $UserAuth = session('auth');
    $info = [];
    foreach ($arr as $v) {
        if (isset($v[$child_name]) && !empty($v[$child_name]) && !in_array($v["name"], ["Index", "Login"])) {
            $cc_arr = [];
            foreach ($v[$child_name] as $kk => $vv) {
                if ($UserAuth["rid"] > 0) {
                    $AuthArr = json_decode($UserAuth["auth"], true); //已拥有的权限
                    if ($vv["isAuth"] && $is_page) {
                        if (in_array($vv["key"], $AuthArr)) {
                            if ($vv["isPage"]) {
                                $cc_arr[] = $vv;
                            }
                        }
                    } else {
                        $cc_arr[] = $vv;
                    }
                } else {
                    if ($is_page) {
                        if ($vv["isPage"]) {
                            $cc_arr[] = $vv;
                        }
                    } else {
                        $cc_arr[] = $vv;
                    }
                }
            }
            $v[$child_name] = $cc_arr;
        } else {
            continue;
        }
        if (!empty($v[$child_name])) {
            $info[] = $v;
        }
    }
    return $info;
}
// function appAttribute(string $app, bool $is_page = true, string $child_name = "child"): array
// {
//     /** @var  $dir_iterator *递归遍历目录查找控制器自动设置路由 */
//     // $dir_iterator = new \RecursiveDirectoryIterator(app_path());
//     $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator(app_path()));
//     /** @var  $suffix *读取config*/
//     $suffix = config('app.controller_suffix', '');
//     $suffix_length = strlen((string)$suffix);
//     $arr = [];
//     $i = 0;
//     foreach ($iterator as $file) {
//         /** 忽略目录和非php文件 */
//         if (is_dir($file) || $file->getExtension() != 'php') {
//             continue;
//         }

//         $file_path = str_replace('\\', '/', $file->getPathname());
//         /** 文件路径里不带controller的文件忽略 */
//         if (!str_contains(strtolower($file_path), '/controller/')) {
//             continue;
//         }

//         /**  只处理带 controller_suffix 后缀的 */
//         if ($suffix_length && substr($file->getBaseName('.php'), -$suffix_length) !== $suffix) {
//             continue;
//         }

//         // 根据文件路径是被类名
//         /** @var  $class_name *根据文件路径获取类名 */
//         $class_name = str_replace('/', '\\', substr(substr($file_path, strlen(base_path())), 0, -4));

//         if (!class_exists((string)$class_name)) {
//             echo "Class $class_name not found, skip route for it\n";
//             continue;
//         }
//         $controller = new \ReflectionClass($class_name);
//         $controllerClass = $controller->getAttributes(app\common\Attribute::class);
//         $title = $controllerClass[0]->newInstance()->title();

//         $ClassShortName = str_replace(config('app.controller_suffix', ''), "", $controller->getShortName()); // 短class名不包括后缀
//         $arr[$i] = ["name" => $ClassShortName, "title" => $title, "spread" => true, "key" => $ClassShortName];

//         foreach ($controller->getMethods(\ReflectionMethod::IS_PUBLIC) as $v) {

//             //淘汰方法
//             if (in_array($v->name, ['__construct', '__destruct'])) {
//                 continue;
//             }

//             $class = new \ReflectionMethod($v->class, $v->name);
//             $attributes = $class->getAttributes(app\common\Attribute::class);


//             preg_match('/app(.*?)controller/', $v->class, $matches);
//             $appName = str_replace('\\', "", $matches[1]); //应用名

//             if ($appName == $app) {

//                 $MethodShortName = $v->name; //方法名

//                 if (empty($attributes)) {
//                     continue;
//                 }

//                 foreach ($attributes as $attribute) {
//                     $data = $attribute->newInstance()->fun();
//                     $data["name"] = $MethodShortName;
//                     $data["spread"] = true;
//                     $data["key"] = $ClassShortName . "@" . $data["name"];
//                     $arr[$i][$child_name][] = $data;
//                 }
//             }
//         }
//         $i++;
//     }
//     $isType = "isAuth";
//     if ($is_page) {
//         $isType = "isPage";
//     }
//     foreach ($arr as $k => $v) {
//         $is = true;
//         foreach ($v[$child_name] as $kk => $vv) {
//             if ($vv[$isType]) {
//                 $is = false;
//             } else {
//                 unset($arr[$k][$child_name][$kk]);
//             }
//         }
//         if ($is || in_array($v["name"], ["Index", "Login"])) {
//             unset($arr[$k]);
//         }
//     }
//     return $arr;
// }

/**
 * 树形数组 function
 *
 * @param array $data
 * @param integer $parentId
 * @return array
 */
function buildTree(array $data, int $parentId = 0): array
{
    $tree = array();

    foreach ($data as $item) {
        if ($item['pid'] == $parentId) {
            $children = buildTree($data, $item['id']);

            if (!empty($children)) {
                $item['children'] = $children;
            }
            $item["icon"] = $item["icon_str"];
            $item["title"] = $item["name"];
            if ($item["is_menu"] == 1) {
                $firstChar = strtolower(substr($item["controller"], 0, 1));
                $restOfString = substr($item["controller"], 1);
                $controller = $firstChar . $restOfString;
                $item["href"] = route(
                    \request()->app . "." .
                        $controller  . "." .
                        $item["method"]
                );
            }
            $tree[] = $item;
        }
    }

    return $tree;
}

/**
 * select无限树形 function
 *
 * @param array $data
 * @param integer $pid
 * @param array $array
 * @param integer $level
 * @param string $separator
 * @return void
 */
function selectTree(array $data = [], int $pid = 0, array &$array = [], $level = 0, $separator = '&nbsp;&nbsp;|---->'): array
{
    foreach ($data as $key => $value) {
        if ($value['pid'] == $pid) {
            $value['level'] = str_repeat($separator, $level); //分隔符修改处,并非一定要当形参引用传入,也可以写死来提升美观性,这里为了便于理解所以当作了形参处理
            $array[] = $value;
            selectTree($data, $value['id'], $array, $level + 1);
        }
    }
    return $array;
}

/**
 * 递归删除文件 function
 *
 * @param string $folder 文件夹路径
 * @return void
 */
function deleteFolder(string $folder)
{
    if (is_dir($folder)) {
        $files = scandir($folder);
        foreach ($files as $file) {
            if ($file != '.' && $file != '..') {
                deleteFolder($folder . '/' . $file);
            }
        }
        rmdir($folder);
    } else {
        unlink($folder);
    }
}

/**
 * 获取控制器短名 function
 *
 * @param string $controller
 * @return string
 */
function getController($controller = ''): string
{
    if ($controller ===  '') {
        $controller = request()->controller;
    }
    return substr(strrchr($controller, '\\'), 1);
}
